<template>
  <div>
    <el-row class="param-list">
      <el-col :span="24" class="parameter-list">
        <div class="p-2" style="text-align: center">
          <!--        <el-button type="primary" size="small" @click="() => editable = true">Edit</el-button>-->
          <el-switch
            v-model="editable"
            :active-text="$t('flyparam.edit_mode')"
            :inactive-text="$t('flyparam.read_mode')"
          />
        </div>
        <el-form ref="form" :model="ruleForm" @submit.native.prevent>
          <el-table
            :key="randomKey"
            cell-class-name="param-list-table-cell"
            :data="ruleForm.tableData"
            border
          >
            <el-table-column type="index" align="center" />
            <el-table-column
              :label="$t('flyparam.param_label')"
              prop="label"
              align="center"
            >
              <template v-slot="scope">
                <el-form-item
                  v-if="editable"
                  :prop="'tableData.' + scope.$index + '.' + 'label'"
                  :rules="[
                    {
                      required: true,
                      message: 'Label is required',
                      trigger: 'change',
                    },
                    { validator: validateLabel, trigger: ['blur', 'change'] },
                  ]"
                >
                  <el-input
                    :ref="scope.column.property"
                    v-model="scope.row.label"
                    :maxlength="64"
                    size="small"
                  />
                </el-form-item>
                <span v-else>{{ scope.row.label }}</span>
              </template>
            </el-table-column>
            <el-table-column :label="$t('flyparam.param_key')" prop="key" align="center">
              <template v-slot="scope">
                <el-form-item
                  :class="{ show: scope.row[scope.column.property + 'isShow'] }"
                  :prop="'tableData.' + scope.$index + '.' + 'key'"
                  :rules="[
                    {
                      required: true,
                      message: 'Key is required',
                      trigger: 'change',
                    },
                    { validator: validateInput, trigger: ['blur', 'change'] },
                  ]"
                >
                  <el-input
                    v-if="editable"
                    :ref="scope.column.property"
                    v-model="scope.row.key"
                    :maxlength="64"
                    size="small"
                  />
                  <span v-else>{{ scope.row.key }}</span>
                </el-form-item>
              </template>
            </el-table-column>
            <el-table-column
              :label="$t('flyparam.param_type')"
              prop="valueType"
              align="center"
            >
              <template v-if="scope.row.type !== 2" v-slot="scope">
                <span>{{ typeLabel(scope.row.valueType) }}</span>
              </template>
            </el-table-column>
            <el-table-column
              v-if="mode === 1"
              :label="$t('flyparam.reference_table')"
              align="center"
            >
              <template v-slot="scope">
                <div v-if="scope.row.valueType === types.REFERENCE">
                  <el-select
                    v-if="editable"
                    v-model="scope.row.table"
                    :loading="selectLoading"
                    size="small"
                    value-key="id"
                    @change="scope.row.defaultValues = []"
                  >
                    <el-option
                      v-for="table in referenceTables"
                      :key="table.id"
                      :label="table.name"
                      :value="{
                        id: table.id,
                        tableType: table.tableType,
                        name: table.name,
                      }"
                    >
                      <svg-icon :icon-class="_treeIconClass(table)" class-name="mr-2" />
                      <span>{{ table.name }}</span>
                    </el-option>
                  </el-select>
                  <span v-else>{{ scope.row.table.name }}</span>
                </div>
              </template>
            </el-table-column>
            <el-table-column
              v-if="mode === 1"
              :label="$t('flyparam.date_formatter')"
              align="center"
            >
              <template v-slot="scope">
                <div
                  v-if="
                    scope.row.valueType === types.TIME ||
                    scope.row.valueType === types.DATETIME ||
                    scope.row.valueType === types.DATE
                  "
                >
                  <el-form-item
                    v-if="editable"
                    :prop="'tableData.' + scope.$index + '.' + 'formatter'"
                    :rules="{
                      required: true,
                      message: 'Required',
                      trigger: 'change',
                    }"
                  >
                    <el-select v-model="scope.row.formatter" size="small">
                      <div v-if="scope.row.valueType === types.TIME">
                        <el-option label="HH:mm:ss" value="HH:mm:ss" />
                      </div>
                      <div v-else-if="scope.row.valueType === types.DATETIME">
                        <el-option
                          label="MM/dd/yyyy HH:mm:ss"
                          value="MM/dd/yyyy HH:mm:ss"
                        />
                        <el-option
                          label="dd/MM/yyyy HH:mm:ss"
                          value="dd/MM/yyyy HH:mm:ss"
                        />
                        <el-option
                          label="yyyy/MM/dd HH:mm:ss"
                          value="yyyy/MM/dd HH:mm:ss"
                        />
                        <el-option
                          label="YYYY-MM-dd HH:mm:ss"
                          value="YYYY-MM-dd HH:mm:ss"
                        />
                      </div>
                      <div v-else-if="scope.row.valueType === types.DATE">
                        <el-option label="MM/dd/yyyy" value="MM/dd/yyyy" />
                        <el-option label="dd/MM/yyyy" value="dd/MM/yyyy" />
                        <el-option label="yyyy/MM/dd" value="yyyy/MM/dd" />
                        <el-option label="YYYY-MM-dd" value="YYYY-MM-dd" />
                      </div>
                    </el-select>
                  </el-form-item>
                  <span v-else>{{ scope.row.formatter }}</span>
                </div>
              </template>
            </el-table-column>
            <el-table-column
              :label="$t('flyparam.default_value')"
              prop="defaultValues"
              align="center"
              width="300"
            >
              <template v-slot="scope">
                <div v-if="editable">
                  <div v-if="scope.row.valueType === types.REFERENCE">
                    <div v-if="scope.row.table && scope.row.table.tableType !== 1">
                      <el-select
                        v-model="scope.row.defaultValues"
                        class="default-value"
                        :popper-class="selectReferenceVisible ? 'hidden' : ''"
                        multiple
                        :multiple-limit="10"
                        collapse-tags
                        size="small"
                        @click.native="() => showSelectReferenceDialog(scope.row)"
                      >
                        <el-option
                          v-for="item in referenceValues"
                          :key="item"
                          :label="item"
                          :value="item"
                        />
                      </el-select>
                    </div>
                  </div>

                  <div v-else-if="scope.row.valueType === types.BOOLEAN">
                    <el-switch v-model="scope.row.defaultValues" />
                  </div>

                  <div v-else-if="scope.row.valueType === types.FILE">
                    <div
                      v-ellipsis
                      class="cursor-pointer"
                      @click.stop="() => showUploadDialog(scope.row)"
                    >
                      <span :class="{ 'text-secondary': !scope.row.defaultValues }">
                        <i class="el-icon-document" />
                        {{ scope.row.defaultValues || "Click to choose a file" }}
                      </span>
                    </div>
                  </div>

                  <div v-else-if="scope.row.valueType === types.TIME">
                    <el-time-picker
                      v-model="scope.row.defaultValues"
                      :format="scope.row.formatter"
                      :value-format="scope.row.formatter"
                      size="small"
                      style="width: 100%"
                    />
                  </div>

                  <div v-else-if="scope.row.valueType === types.DATE">
                    <el-date-picker
                      v-model="scope.row.defaultValues"
                      :format="scope.row.formatter"
                      type="date"
                      size="small"
                      style="width: 100%"
                    />
                  </div>

                  <div v-else-if="scope.row.valueType === types.DATETIME">
                    <el-date-picker
                      v-model="scope.row.defaultValues"
                      :format="scope.row.formatter"
                      type="datetime"
                      size="small"
                      style="width: 100%"
                    />
                  </div>

                  <div v-else>
                    <el-form-item
                      :prop="'tableData.' + scope.$index + '.' + 'defaultValues'"
                      :rules="defaultValuesRules(scope.row)"
                    >
                      <el-input
                        v-if="editable"
                        :ref="scope.column.property"
                        v-model="scope.row.defaultValues"
                        :maxlength="scope.row.maxLength"
                        size="small"
                        @input="(val) => handleStringInput(val, scope.row)"
                      />
                      <span v-else>{{ scope.row.defaultValues }}</span>
                    </el-form-item>
                  </div>
                </div>
                <template v-else>
                  <div v-if="scope.row.valueType === types.REFERENCE">
                    <span v-if="scope.row.table">
                      {{ scope.row.defaultValues.join(",") }}
                    </span>
                  </div>
                  <div v-else-if="scope.row.valueType === types.BOOLEAN">
                    {{ scope.row.defaultValues.toString() }}
                  </div>
                  <div
                    v-else-if="[types.DATE, types.DATETIME].includes(scope.row.valueType)"
                  >
                    {{ date2String(scope.row) }}
                  </div>
                  <div v-else>
                    {{ scope.row.defaultValues }}
                  </div>
                </template>
              </template>
            </el-table-column>

            <el-table-column
              :label="$t('flyparam.max_length')"
              align="center"
              prop="maxLength"
            >
              <template
                v-if="
                  ![
                    types.BOOLEAN,
                    types.FILE,
                    types.TIME,
                    types.DATE,
                    types.DATETIME,
                  ].includes(scope.row.valueType)
                "
                v-slot="scope"
              >
                <el-form-item
                  v-if="scope.row[scope.column.property + 'isShow']"
                  :prop="'tableData.' + scope.$index + '.' + 'maxLength'"
                  :rules="maxLengthRules(scope.row)"
                >
                  <el-input
                    :ref="scope.column.property"
                    v-model.number="scope.row.maxLength"
                    type="number"
                    :maxlength="255"
                    size="small"
                    @input="(val) => handleHexMaxLengthInput(val, scope.row)"
                    @blur="
                      alterData(
                        scope.row,
                        scope.column,
                        'tableData.' + scope.$index + '.' + 'maxLength'
                      )
                    "
                  />
                </el-form-item>
                <span v-else>{{ scope.row.maxLength }}</span>
              </template>
            </el-table-column>

            <el-table-column
              :label="$t('flyparam.param_require')"
              align="center"
              prop="nullable"
            >
              <template
                v-if="scope.row.type !== 2 && scope.row.valueType !== types.BOOLEAN"
                v-slot="scope"
              >
                <el-switch
                  v-model="scope.row.nullable"
                  :active-value="0"
                  :inactive-value="1"
                  :disabled="!editable"
                />
              </template>
            </el-table-column>

            <el-table-column
              :label="$t('common.description')"
              align="center"
              prop="description"
            >
              <template v-slot="scope">
                <el-form-item :prop="'tableData.' + scope.$index + '.' + 'description'">
                  <el-input
                    v-if="scope.row[scope.column.property + 'isShow']"
                    :ref="scope.column.property"
                    v-model="scope.row.description"
                    size="small"
                    @blur="
                      alterData(
                        scope.row,
                        scope.column,
                        'tableData.' + scope.$index + '.' + 'description'
                      )
                    "
                  />
                  <span v-else>{{ scope.row.description }}</span>
                </el-form-item>
              </template>
            </el-table-column>

            <!-- <el-table-column align="center" label="Operation">
            <template v-slot="{row}">
              <el-button v-if="!row.editable" type="text" @click="() => row.editable = true">Edit</el-button>
              <el-button v-else type="text" @click="() => handleRowConfirm(row)">OK</el-button>
            </template>
          </el-table-column> -->
          </el-table>
        </el-form>
      </el-col>
      <select-reference
        v-if="currentItem"
        :current-item="currentItem"
        v-model="selectReferenceVisible"
        :table-id="tableId"
        :template-id="templateId"
      />
      <upload-file
        v-model="uploadFileVisible"
        :current-item="currentItem"
        @confirm="(filePath) => handleFileUploadConfirm(filePath)"
      />
      <layout-preview
        :table-id="tableId"
        v-model="layoutPreviewVisible"
        :template-id="templateId"
      />
    </el-row>
  </div>
</template>

<script>
import { getReferenceEntryRecord, getReferenceTable } from "@/api/parameter";
import { types } from "../constant";
import SelectReference from "./select-reference";
import UploadFile from "./upload-file";
import LayoutPreview from "./layout-preview";
import { deepClone } from "@/utils";
import { validateNumber, validateHex, validateLabel, validateInput } from "../validate";
import { formatDateParameter, treeIconClass } from "../helper";
import Clickoutside from "@/directives/clickoutside";

function validateHexMaxLength(rule, value, callback) {
  if (Number(value) > rule.maxLength) {
    rule.item.maxLength = 2048;
  }
  callback();
}

export default {
  components: {
    SelectReference,
    UploadFile,
    LayoutPreview,
  },
  directives: { Clickoutside },
  props: {
    tableData: {
      type: Array,
    },
    disabled: {
      type: Boolean,
      default: false,
    },
    tabId: {
      type: String,
    },
    templateId: String,
    tab: Object,
    mode: Number, // 模式，设计模式 = 1 ， 简单模式 = 2
  },
  data() {
    return {
      randomKey: Math.random(),
      refTableSchemaId: "",
      types,
      selectReferenceVisible: false,
      currentItem: null,
      uploadFileVisible: false,
      layoutPreviewVisible: false,
      referenceValues: [],
      tableId: "",
      editable: false,
      validateLabel,
      validateInput,
      referenceTables: [],
      selectLoading: true,
    };
  },
  computed: {
    ruleForm() {
      return {
        tableData: this.tableData,
      };
    },
  },
  mounted() {
    // this.eventBus.$on('save');
  },
  methods: {
    editCell(row, column) {
      if (!row[column.property + "isShow"]) {
        if (column.label !== "Mandotary" && row.valueType !== types.BOOLEAN) {
          row[column.property + "isShow"] = true;
          this.refreshTable();
          this.$nextTick(() => {
            this.$refs[column.property] && this.$refs[column.property].focus();
          });
        }
      }
    },
    fetchReferenceTable() {
      this.selectLoading = true;
      getReferenceTable(this.templateId, this.tabId)
        .then((data) => {
          this.referenceTables = data;
        })
        .finally(() => {
          this.selectLoading = false;
        });
    },
    date2String(parameter) {
      return formatDateParameter(parameter, "defaultValues");
    },
    alterData(row, column, prop) {
      this.$refs.form.validateField(prop, (errorMessage) => {
        if (!errorMessage) {
          row[column.property + "isShow"] = false;
          this.refreshTable();
        }
      });
    },
    refreshTable() {
      this.randomKey = Math.random();
    },
    handleSelectReference() {
      this.selectReferenceVisible = true;
      // if (this.currentItem.refTableSchemaId) {
      // } else {
      //   this.$message.error(this.$t('flyparam.select_table_warning'))
      // }
    },
    handleValueTypeChange(val, prop, row) {
      this.$refs.form.clearValidate(prop);
      row.defaultValues = "";
      row.formatter = "";
    },
    handleRowConfirm(row) {
      row.editable = false;
    },
    showSelectReferenceDialog(row) {
      this.tableId = row.table.id;
      if (row.table.tableType === 3) {
        getReferenceEntryRecord(this.templateId, row.table.id, {
          pageNo: 1,
          pageSize: 30,
        }).then((data) => {
          const value = data.items.map((item) => {
            return item.$label[0];
          });
          this.referenceValues = value;
        });
      } else if (row.table.tableType === 1) {
        this.layoutPreviewVisible = true;
      } else {
        this.currentItem = row;
        this.$nextTick(() => {
          this.handleSelectReference();
        });
      }
    },
    showUploadDialog(row) {
      this.uploadFileVisible = true;
      this.currentItem = row;
    },
    handleFileUploadConfirm(filePath) {
      const item = this.tableData.find((item) => item.i === this.currentItem.i);
      this.$set(item, "defaultValues", filePath);
    },
    handleHexMaxLengthInput(val, row) {
      row.maxLength = Number((val + "").replace(/[-.]/g, ""));
    },
    _treeIconClass(data) {
      return treeIconClass(data);
    },
    handleStringInput(val, row) {
      this.tab.form[row.i] = val;
    },
    defaultValuesRules(row) {
      const required = row.nullable === 0;
      const rules = {
        [types.NUMBER]: [
          {
            maxLength: row.maxLength,
            required: row.nullable,
            validator: validateNumber.bind(row),
          },
        ],
        [types.HEX]: [
          {
            required,
            validator: validateHex.bind(row),
          },
        ],
      };
      return rules[row.valueType];
    },
    maxLengthRules(row) {
      const rules = {
        [types.HEX]: [
          {
            validator: validateHexMaxLength.bind(row),
            trigger: "change",
            item: row,
            maxLength: 2048,
          },
        ],
      };
      return rules[row.valueType];
    },
    typeLabel(type) {
      const TYPES_MAP = {
        [types.STRING]: "String",
        [types.BOOLEAN]: "Boolean",
        [types.NUMBER]: "Number",
        [types.HEX]: "Hex",
        [types.REFERENCE]: "Reference",
        [types.FILE]: "File",
        [types.TIME]: "Time",
        [types.DATE]: "Date",
        [types.DATETIME]: "DateTime",
      };
      return TYPES_MAP[type];
    },
    cancel() {
      this.ruleForm.tableData = deepClone(this.tableData);
      this.editable = false;
    },
  },
};
</script>

<style lang="scss" scoped>
::v-deep .el-form-item {
  margin-bottom: 0px;

  &.show {
    margin-bottom: 20px;
  }

  .el-form-item__error {
    position: static;
  }
}

::v-deep {
  .default-value.el-select {
    width: 100%;
  }
}
</style>
